﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Diagnostics;

namespace emulib
{
    public class ConnectionManager
    {
        public delegate T Action<T>(T args);
        public delegate void ActionCalled(Object sender, EventArgs e);
        public event ActionCalled actionCalled;
        Boolean _isRunning;
        public Boolean Running
        {
            get { return _isRunning; }
            set
            {
                if (value)
                {
                    StartListener();
                }
                else
                {
                    StopListener();
                }
            }
        }
        ThreadPriority _listenerThreadPriority;
        public ThreadPriority listenerThreadPriority
        {
            get { return _listenerThreadPriority; }
            set
            {
                if (_isRunning)
                {
                    listenerThread.Priority = value;
                    _listenerThreadPriority = value;
                }
            }
        }
        Dictionary<Byte[], Action> actions = new Dictionary<Byte[], Action>();
        IPAddress ip;
        Int32 port;
        SocketType sockType;
        ProtocolType protoType;
        AddressFamily addrFamily;
        Thread listenerThread;
        Boolean killRequest = false;
        public ConnectionManager(Dictionary<Byte[], Action> opList, IPAddress listenIP, UInt16 listenPort, SocketType sockType = SocketType.Stream, ProtocolType protoType = ProtocolType.Tcp, AddressFamily addrFamily = AddressFamily.InterNetwork)
        {
            actions = opList;
            ip = listenIP;
            port = listenPort;
            this.sockType = sockType;
            this.protoType = protoType;
            this.addrFamily = addrFamily;
            StartListener();
        }
        void Listener()
        {
            Boolean gracefulAbort = false;
            try
            {
                while (true)
                {
                    if (killRequest)
                    {
                        Extras.ServConsoleWrite("Abort request received, gracefully stopping");
                        gracefulAbort = true;
                        listenerThread.Abort();
                    }
                    Extras.ServConsoleWrite("Simulating a really long task");
                    Thread.Sleep(1000);
                }
            }
            catch (ThreadAbortException e)
            {
                if (!gracefulAbort)
                {
                    Extras.ServConsoleWrite(e.Message);
                    Extras.ServConsoleWrite("Listener thread terminated forcefully.");
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
        public void StartListener()
        {
            listenerThread = new Thread(new ThreadStart(Listener));
            listenerThread.Start();
            _isRunning = true;
        }
        public void StopListener()
        {
            if (_isRunning)
            {
                killRequest = true;
                Debug.WriteLine(killRequest);
                //this is why I didn't use backgroundworker...
                if (!listenerThread.Join(5000))
                {
                    listenerThread.Abort();
                    //just in case it got stuck on something
                    listenerThread.Priority = ThreadPriority.Lowest;
                }
            }
        }
    }
}
